#include <iostream>
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include <fstream>
#include "util.hpp"

const std::string scr_path = "data/input/";
const std::string output = "data/raw_html/raw.txt";

typedef struct DocInfo
{
    std::string title;   // 文档的标题
    std::string content; // 文档的内容
    std::string url;     // 文档在官网中的url
} DocInfo_t;

// const &:输入型参数
//   *    ：输出型参数
//   &    :输入输出型参数
static bool EnumFile(const std::string &scr_path, std::vector<std::string> *files_list);
static bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results);
static bool SaveHtml(std::vector<DocInfo_t> &results, const std::string &output);

int main()
{
    std::vector<std::string> files_list;
    // 第一步：递归式的把每个html的文件名加入到files_list中，方便之后提取内容
    if (!EnumFile(scr_path, &files_list))
    {
        std::cerr << "enum file name error!" << std::endl;
        return 1;
    }

    std::vector<DocInfo_t> results;
    // 第二步：按照files_list吧文件里的内容解析到result里面
    if (!ParseHtml(files_list, &results))
    {
        std::cerr << "parse file  error!" << std::endl;
        return 2;
    }

    // 第三步：把result里面的内容塞进output里面,按照\3为分隔符
    if (!SaveHtml(results, output))
    {
        std::cerr << "save file error!" << std::endl;
        return 3;
    }

    return 0;
}
static bool EnumFile(const std::string &scr_path, std::vector<std::string> *files_list)
{
    namespace fs = boost::filesystem;
    fs::path root_path(scr_path);

    // 判断路径是否存在
    if (!fs::exists(root_path))
    {
        std::cerr << "not exists" << std::endl;
        return false;
    }

    // 创建一个空的迭代器，用来递归结束
    fs::recursive_directory_iterator end;
    // 递归查找是否是普通文件，是否是html后缀
    for (fs::recursive_directory_iterator iter(root_path); iter != end; iter++)
    {
        if (!fs::is_regular_file(*iter))
        {
            // std::cerr<<"not regular file"<<std::endl;
            continue;
        }
        if (iter->path().extension() != ".html")
        {
            // std::cerr<<" not html"<<std::endl;
            continue;
        }
        // 判断完之后入，方便后续分析
        files_list->push_back(iter->path().string());
    }
    return true;
}

static bool ParserTitle(const std::string &file, std::string *title)
{
    std::size_t begin = file.find("<title>");
    if (begin == std::string::npos)
    {
        std::cerr << "not find <title>" << std::endl;
        return false;
    }

    std::size_t end = file.find("</title>");
    if (begin == std::string::npos)
    {
        std::cerr << "not find </title>" << std::endl;
        return false;
    }

    begin += std::string("<title>").size();
    if (begin > end)
    {
        return false;
    }
    *title = file.substr(begin, end - begin);
    return true;
}
static bool ParserContent(const std::string &file, std::string *content)
{
    // 去标签，基于一个简单的状态机
    enum status
    {
        TABLE,
        CONTENT
    };

    status st = TABLE;
    for (char f : file)
    {
        switch (st)
        {
        case TABLE:
            if(f=='>') st=CONTENT;
            break;
        case CONTENT:
            if(f=='<') st=TABLE;
            //不保留文件中的\n我们之后解析需要用\n做分隔符
            if(f=='\n') f=' ';
            content->push_back(f);
            break;
        default:
            break;
        }
    }
    return true;
}
static bool ParserUrl(const std::string &file, std::string *url)
{
    //官方文档的网址
    std::string url_head="https://www.boost.org/doc/libs/1_89_0/doc/html/";
    std::string url_tail= file.substr(scr_path.size());

    *url=url_head+url_tail;
    return true;
}

void ShowDoc(DocInfo_t& doc)
{
    std::cout<<"title: "<<doc.title<<std::endl;
    std::cout<<"content: "<<doc.content<<std::endl;
    std::cout<<"url: "<<doc.url<<std::endl;
}
static bool ParseHtml(const std::vector<std::string> &files_list, std::vector<DocInfo_t> *results)
{
    for (const std::string &file : files_list)
    {
        // 第一步先读取内容
        std::string result;
        if (!ns_util::FileUtil::ReadFile(file, &result))
        {
            continue;
        }

        DocInfo_t doc;
        // 第二步解析标题
        if (!ParserTitle(result, &doc.title))
        {
            continue;
        }

        // 第三步解析内容
        if (!ParserContent(result, &doc.content))
        {
            continue;
        }

        // 第四步解析url
        if (!ParserUrl(file, &doc.url))
        {
            continue;
        }

        // 到这里说明解析都没问题
        results->push_back(std::move(doc));//减少拷贝
        // ShowDoc(doc);//forbebug
        // break;
    }
    return true;
}
static bool SaveHtml(std::vector<DocInfo_t> &results, const std::string &output)
{
    //title/3content\3url\n
#define SEP '\3'
    std::ofstream out(output,std::ios::binary|std::ios::out);

    for(auto& r:results)
    {
        std::string out_string;
        out_string=r.title;
        out_string+=SEP;
        out_string+=r.content;
        out_string+=SEP;
        out_string+=r.url;
        out_string+='\n';

        out.write(out_string.c_str(),out_string.size());
    }
    out.close();
    return true;
}